package com.scanx.thread;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 线程工具类
 *
 * @author alpha.
 * @className ThreadUtil
 * @date 2024/2/6 15:02
 */
public class ThreadPoolUtil {


    /**
     * 支持自定义线程池阻塞队列最大值
     *
     * @param maxQueueSize
     * @return 线程池
     */
    public static ThreadPoolExecutor newThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, String namePrefix, int maxQueueSize) {
        maxQueueSize = maxQueueSize == -1 ? Integer.MAX_VALUE : maxQueueSize;
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                corePoolSize,
                maximumPoolSize,
                keepAliveTime,
                unit,
                new LinkedBlockingQueue<>(maxQueueSize),
                newThreadFactory(namePrefix),
                new ThreadPoolExecutor.CallerRunsPolicy());
        return executor;
    }

    /**
     * 自定义线程池
     *
     * @param corePoolSize    核心线程数量
     * @param maximumPoolSize 最大线程数量
     * @param keepAliveTime   线程存活时间
     * @param unit            时间单位
     * @param namePrefix      线程名称前缀
     * @return 线程池
     */
    public static ThreadPoolExecutor newThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, String namePrefix) {
        return newThreadPool(corePoolSize, maximumPoolSize, keepAliveTime, unit, namePrefix, -1);
    }

    /**
     * 支持自定义线程名称的线程工厂
     *
     * @param namePrefix 名称前缀
     * @return 线程工厂
     */
    private static ThreadFactory newThreadFactory(String namePrefix) {
        ThreadFactory factory = new ThreadFactory() {
            private final AtomicInteger threadNumber = new AtomicInteger(1);

            @Override
            public Thread newThread(Runnable r) {
                Thread t = new Thread(Thread.currentThread().getThreadGroup(), r, namePrefix + "-" + threadNumber.getAndIncrement());
                if (t.isDaemon()) {
                    t.setDaemon(false);
                }
                if (t.getPriority() != Thread.NORM_PRIORITY) {
                    t.setPriority(Thread.NORM_PRIORITY);
                }
                return t;
            }
        };
        return factory;
    }
}
